#include <iostream>
#include "stdTcpServer.h"
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

#define SERVER_PORT 8080

// 构造函数
StdTcpSocket::StdTcpSocket() : m_sockAttr(std::make_unique<stdTcpSocketPrivate>())
{
    m_sockAttr->connfd = -1;
    m_sockAttr->m_connected = false;
}

// 析构函数
StdTcpSocket::~StdTcpSocket()
{
    if (m_sockAttr->connfd > 0)
    {
        close(m_sockAttr->connfd);
    }
}

// 连接服务器
int StdTcpSocket::connectToServer(const char *ip, int port)
{
    // 创建socket套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket error");
        return -1;
    }
    std::cout << "sockfd:" << sockfd << std::endl;

    // 连接服务器
    // 这一步是配置服务器地址，告诉客户端要连接哪个端口
    // 使用了传入的 port 参数，可以灵活连接不同的服务器端口
    struct sockaddr_in serverAddr;            // 是一个结构体，用来保存服务器的地址信息，包括 IP 地址和端口号
    serverAddr.sin_family = AF_INET;          // 这里指定使用的是 IPv4 协议
    serverAddr.sin_port = htons(SERVER_PORT); // 将传入的端口号转换为网络字节序

    // 将字符串形式的 IP 地址（192.168.27.129）转换为二进制形式
    // 并存储在 serverAddr.sin_addr.s_addr 中
    const char *serverIp = "192.168.27.129";
    inet_pton(AF_INET, serverIp, &(serverAddr.sin_addr.s_addr));

    // 发起连接请求
    int ret = connect(sockfd, reinterpret_cast<const sockaddr *>(&serverAddr), sizeof(serverAddr));
    if (ret != 0)
    {
        perror("connect error");
        return -1;
    }
    // 程序执行到这：连接服务器成功...

    // 更新连接状态
    m_sockAttr->connfd = sockfd;
    m_sockAttr->m_connected = true;

    return 0;
}

// 是否连接成功
bool StdTcpSocket::isConnected() const
{
    return m_sockAttr->m_connected;
}

// 发送数据
int StdTcpSocket::sendMessage(const std::string &sendMsg)
{
    return sendMessage(sendMsg.c_str(), sendMsg.size());
}

int StdTcpSocket::sendMessage(const void *sendMsg, size_t n)
{
    // int writeBytes = write(m_sockAttr->connfd, sendMsg, n);
    // return writeBytes;

    // 1、先发数据包的大小
    int writeBytes = write(m_sockAttr->connfd, (const void *)&n, sizeof(n));
    if (writeBytes < 0)
    {
        perror("write error");
        return -1;
    }

    // 2、再发数据本身
    writeBytes = write(m_sockAttr->connfd, sendMsg, n);
    if (writeBytes < 0)
    {
        perror("write error");
        return -1;
    }

    return writeBytes;
}

// 接收数据
int StdTcpSocket::recvMessage(std::string &recvMessage)
{
    size_t dataSize = 0;
    int readBytes = read(m_sockAttr->connfd, (void *)&dataSize, sizeof(size_t));
    if (readBytes <= 0)
    {
        perror("read error");
        return -1;
    }
    // std::cout << "size:" << dataSize << std::endl;
    // 程序到这个地方：就可以知道后面的数据有多长

    char *msg = new char[dataSize + 1];
    // 清除脏数据
    memset(msg, 0, sizeof(char) * (dataSize + 1));

    int totalReceived = 0;
    while (totalReceived < dataSize)
    {
        size_t received = read(m_sockAttr->connfd, msg + totalReceived, dataSize - totalReceived);
        if (received <= 0)
        {
            perror("read error");
            delete[] msg;
            return -1;
        }

        totalReceived += received;
    }
    // 接收到的数据
    recvMessage = msg;
    delete[] msg;

    return totalReceived;
}

int StdTcpSocket::recvMessage(void *buf, size_t n)
{
    int readBytes = read(m_sockAttr->connfd, buf, n);
    return readBytes;

    // // 1、先接收数据包的大小
    // size_t dataSize = 0;
    // int readBytes = read(m_sockAttr->connfd, &dataSize, sizeof(dataSize));
    // if (readBytes < 0)
    // {
    //     perror("read error");
    //     return -1;
    // }

    // // 2、再接收数据本身
    // size_t recvData = 0;
    // readBytes = read(m_sockAttr->connfd, (char *)buf)
}

// 得到属性
stdTcpSocketPrivate *StdTcpSocket::getSockAttr() const
{
    return m_sockAttr.get();
}

// 无参构造
StdTcpServer::StdTcpServer() : m_tcpAttr(std::make_unique<stdTcpServerPrivate>())
{
    m_tcpAttr->m_sockfd = -1;
    m_tcpAttr->m_isRunning = false;
}

// 析构函数
StdTcpServer::~StdTcpServer()
{
    if (m_tcpAttr->m_sockfd > 0)
    {
        close(m_tcpAttr->m_sockfd);
    }
}

// 设置监听
bool StdTcpServer::setListen(int port)
{
    // 类内部维护端口信息
    this->m_port = port;

    // 创建套接字
    m_tcpAttr->m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (m_tcpAttr->m_sockfd == -1)
    {
        perror("socket error");
        throw std::runtime_error("socket creat failed");
    }

    // 设置端口复用
    int optVal = 1;
    int ret = setsockopt(m_tcpAttr->m_sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
    if (ret != 0)
    {
        perror("bind error");
        return false;
    }

    // 绑定IP和端口信息
    struct sockaddr_in localAddress;
    // 清空结构体的脏数据
    memset(&localAddress, 0, sizeof(localAddress));
    // 地址族是IPV4
    localAddress.sin_family = AF_INET;
    localAddress.sin_port = htons(m_port);
    // 设置全通规则
    localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    // 绑定
    ret = bind(m_tcpAttr->m_sockfd, reinterpret_cast<const struct sockaddr *>(&localAddress), sizeof(localAddress));
    if (ret != 0)
    {
        perror("bind error");
        throw std::runtime_error("bind failed");
    }
    // 给套接字设置监听
    ret = listen(m_tcpAttr->m_sockfd, 10);
    if (ret != 0)
    {
        perror("listen error");
        throw std::runtime_error("listen failed");
    }

    m_tcpAttr->m_isRunning = true;

    return true;
}

// 接收客户端的连接
std::shared_ptr<StdTcpSocket> StdTcpServer::getClientSock()
{
    int clientConnfd = accept(m_tcpAttr->m_sockfd, NULL, NULL);
    if (clientConnfd == -1)
    {
        perror("accept error");
        throw std::runtime_error("accept failed");
    }

    // 程序到了这个地方，就说明有客户端连接
    std::cout << "clientConnfd:" << clientConnfd << std::endl;

    // 通信类
    auto client = std::make_shared<StdTcpSocket>();

    // 套接字
    client->getSockAttr()->connfd = clientConnfd;
    client->getSockAttr()->m_connected = true;

    return client;
}
